﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EzyThirdLogic
{
    public class FunctionalDependencySetCollection
    {
        #region Private Fields

        private ISet<FunctionalDependencySet> _fdSetCollection;

        #endregion

        #region Constructors

        public FunctionalDependencySetCollection()
        {
            _fdSetCollection = new SortedSet<FunctionalDependencySet>();
        }

        public FunctionalDependencySetCollection(FunctionalDependencySet fdSet)
        {
            _fdSetCollection = new SortedSet<FunctionalDependencySet>();
            _fdSetCollection.Add(new FunctionalDependencySet(fdSet));
        }

        #endregion

        #region Properties

        public ISet<FunctionalDependencySet> FDSetCollection
        {
            get { return _fdSetCollection; }
            set { _fdSetCollection = value; }
        }

        #endregion

        #region Public Methods

        public void AddFunctionalDependencySet(FunctionalDependencySet fdSet)
        {
            _fdSetCollection.Add(fdSet);
        }

        public void RemoveFunctionalDependency(FunctionalDependencySet fdSet)
        {
            _fdSetCollection.Remove(fdSet);
        }

        public int CountFunctionalDependency()
        {
            int count = 0;

            foreach (FunctionalDependencySet fdSet in _fdSetCollection)
            {
                count += fdSet.FDSet.Count;
            }

            return count;
        }

        public int CountFunctionalDependencySet()
        {
            return _fdSetCollection.Count;
        }

        public override string ToString()
        {
            string result = "";

            for (int i = 0; i < FDSetCollection.Count; i++)
            {
                result += "G" + (i + 1) + " = {";
                var fdSet = FDSetCollection.ElementAt<FunctionalDependencySet>(i);

                for (int j = 0; j < fdSet.FDSet.Count; j++)
                {
                    result += fdSet.FDSet.ElementAt<FunctionalDependency>(j).ToString();
                    if (j != fdSet.FDSet.Count - 1)
                    {
                        result += ", ";
                    }
                }

                result += "}\n";
            }

            return result;
        }

        public string[][] FDSetCollectionToArray(int numFD)
        {
            string[][] bs = new string[numFD][];
            for (int j = 0; j < bs.Length; j++)
            {
                bs[j] = new string[2];
            }

            int i = 0;
            
            foreach (var fdSet in this.FDSetCollection)
            {
                foreach (var fd in fdSet.FDSet)
                {
                    bs[i][0] = AddDelimiter(fd.LeftToString());
                    bs[i][1] = AddDelimiter(fd.RightToString());
                    i++;
                }
            }
            
            return bs;
        }

        public string AddDelimiter(string s)
        {
            string newStr = "";
            for (int i = 0; i < s.Length; i++)
            {
                newStr = newStr + s.Substring(i, 1);
                if (i + 1 != s.Length)
                {
                    newStr += ",";
                }
            }
            return newStr;
        }

        public LinkedList<string> FDSetCollectionToRelation()
        {
            int i = 0;
            LinkedList<string> listFDSet = new LinkedList<string>();

            foreach (var fdSet in this.FDSetCollection)
            {
                string s = "";
                string key = "";
                int j = 0;
                i++;

                foreach (var fd in fdSet.FDSet)
                {
                    if (j == 0)
                    {
                        key = fd.LeftToString();
                        s = CombineAttributes(AddDelimiter(fd.LeftToString()), fd.RightToString());
                        j++;
                    }
                    else
                    {
                        s = CombineAttributes(s, fd.LeftToString());
                        s = CombineAttributes(s, fd.RightToString());
                        if (key.IndexOf(fd.LeftToString()) == -1)
                        {
                            key += ", " + fd.LeftToString();
                        }
                    }
                }

                if (s != "")
                {
                    s = "R" + i + " = (" + s + ")    key = " + key;
                    listFDSet.AddLast(s);
                }
                else
                {
                    i--;
                }
            }

            return listFDSet;
        }

        public string CombineAttributes(string s, string substr)
        {
            for (int i = 0; i < substr.Length; i++)
            {
                if (s.IndexOf(substr.Substring(i, 1)) == -1)
                {
                    s += "," + substr.Substring(i, 1);
                }
            }
            return s;
        }

        #endregion
    }
}
